package org.ccay.sitemap.service.impl.internal;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Named;

import org.ccay.core.log.ILogger;
import org.ccay.core.log.CcayLoggerFactory;
import org.ccay.core.request.impl.RequestContext;
import org.ccay.core.util.CollectionUtil;
import org.ccay.core.util.StringUtil;
import org.ccay.sitemap.SiteMapApplicationException;
import org.ccay.sitemap.SiteNodeSimpleVO;
import org.ccay.sitemap.SiteNodeVO;
import org.ccay.sitemap.service.internal.ISiteMapBuilder;

/**
 * siteMap树构造类
 * 
 * @author chaowangbang
 * @since 2011-10-18
 */
@Named
public class SiteMapBuilder implements ISiteMapBuilder {

	private static final ILogger log = CcayLoggerFactory
			.getLogger(SiteMapBuilder.class);

	/**
	 * 根据语言解析每个节点的名字
	 * 
	 * @author chaowangbang
	 * @since 2011-10-25
	 * @param siteMapNode
	 */
	private void parseSiteNodeName(SiteNodeVO siteMapNode, String language) {
		String name = siteMapNode.getName();
	//	String language = RequestContext.getCurrent().getUserLanguage();		
		
		//取到配置的菜单名中英文的分割
		String[] nameLanguage = name.split(",");
		//循环遍历语言信息
		for(int i=0;i<nameLanguage.length;i++){
			String[] lang=nameLanguage[i].split("=");
			//查找节点当前语言的名称
			if(lang.length>1 && lang[0].equals(language)){				
				siteMapNode.setName(lang[1]);	
				break;
			}
		}
		//如果没有国际化就设置为数据库保存的名称
		if(StringUtil.isNullOrEmpty(siteMapNode.getName())){
			siteMapNode.setName(name);	
		}

	}

	/*构造树
	 * (non-Javadoc)
	 * 
	 * @see org.ccay.sitemap.service.internal.ISiteMapBuilder#buildWholeSiteMap(java.util.List)
	 */
	public SiteNodeVO buildWholeSiteMap(List<SiteNodeVO> allNodes)
			throws SiteMapApplicationException {
		return buildWholeSiteMap(allNodes, 0);
	}

	/*
	 * 构造子树
	 * @see org.ccay.sitemap.service.internal.ISiteMapBuilder#buildWholeSiteMap(java.util.List, java.lang.String)
	 */
	public SiteNodeVO buildWholeSiteMap(List<SiteNodeVO> allNodes, int parentId)
			throws SiteMapApplicationException {
		SiteNodeVO rootNode = getRootNode(allNodes, parentId);

		Map<Integer, SiteNodeVO> allNodesMapping = new HashMap<Integer, SiteNodeVO>(
				allNodes.size());
		//把所有节点保存进map
		for (SiteNodeVO node : allNodes) {
			allNodesMapping.put(node.getSiteNodeId(), node);
		}

		String language = RequestContext.getCurrent().getUserLanguage();
		buildAllToTree(rootNode, allNodes, allNodesMapping, language);
		return rootNode;
	}
	
	/**
	 * 获取首节点 （根据父节点为0的逻辑获取）
	 * 
	 * @author chaowangbang
	 * @since 2011-12-8
	 * @param allNodes
	 * @return
	 * @throws SiteMapApplicationException
	 */
	private SiteNodeVO getRootNode(List<SiteNodeVO> allNodes, int parentId)
			throws SiteMapApplicationException {
		for (SiteNodeVO node : allNodes) {
			if (node.getParent().getSiteNodeId() == 0) {
				return node;
			}
		}
		// 找不到根节点
		throw new SiteMapApplicationException("ccay.sitemap.00010005");
	}

	/**
	 * 为list格式的siteNode数据添加树形层级关系
	 * 
	 * @param rootNode
	 * @param allNodes
	 * @param allNotesMap
	 */
	private void buildAllToTree(SiteNodeVO rootNode, List<SiteNodeVO> allNodes,
			Map<Integer, SiteNodeVO> allNotesMap, String language) {
		for (SiteNodeVO currentNode : allNodes) {
			parseSiteNodeName(currentNode, language);

			SiteNodeVO parent;

			int currentSiteNodeId = currentNode.getSiteNodeId();
			int parentId = currentNode.getParent().getSiteNodeId();

			parent = generateParent(rootNode, allNotesMap, parentId);
			// 丢弃自循环节点和无父节点
			if (parentId == currentSiteNodeId || null == parent) {
				continue;
			}
			// 不需要设置父
			// currentNode.setParent(parent.cloneBaseAttribute());
			if (null == parent.getChildren()) {
				parent.setChildren(new ArrayList<SiteNodeVO>());
			}
			parent.getChildren().add(currentNode);
		}
	}

	/**
	 * 生成父节点
	 * 
	 * @param rootNode
	 * @param allNotesMap
	 * @param parentId
	 * @return
	 */
	private SiteNodeVO generateParent(SiteNodeVO rootNode,
			Map<Integer, SiteNodeVO> allNotesMap, int parentId) {
		if (parentId == rootNode.getSiteNodeId()) {
			return rootNode;
		} else {
			return allNotesMap.get(parentId);
		}
	}

	//private static MessageFormat accessNameFormat = new MessageFormat("{0}/{1}");

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.ccay.sitemap.service.internal.ISiteMapBuilder#buildRoleSiteMap(java.util.Collection,
	 *      org.ccay.sitemap.SiteNodeVO)
	 */
	public SiteNodeSimpleVO buildRoleSiteMap(Collection<String> operations,
			SiteNodeVO fullMapRoot) {

		// 把权限映射为map,便于查询比对
		/***********************************************************************
		 * Collection<String> operations = new HashSet<String>(); for
		 * (OperationDefinitionVO grantedOperation : grantedOperations) {
		 * operations.add(accessNameFormat.format(new String[] {
		 * grantedOperation.getResource().getResourceCode(),
		 * grantedOperation.getOperationCode() })); }
		 **********************************************************************/
		// 构建根节点
		SiteNodeSimpleVO mapRoot = new SiteNodeSimpleVO(fullMapRoot);
		// 处理子节点
		processChildren(mapRoot, fullMapRoot.getChildren(), operations);
		return mapRoot;
	}

	/**
	 * 处理所有子
	 * 
	 * @param parent
	 * @param children
	 * @param grantedOperations
	 * @return
	 */
	private void processChildren(SiteNodeSimpleVO parent,
			List<SiteNodeVO> children, Collection<String> grantedOperations) {
		if (CollectionUtil.isNullOrEmpty(children)) {
			return;
		}

		log.trace("Before process children for " + parent.getName());

		List<SiteNodeSimpleVO> visibleChilren = new ArrayList<SiteNodeSimpleVO>();

		for (SiteNodeVO fullMapNode : children) {
			SiteNodeSimpleVO roledNode = new SiteNodeSimpleVO(fullMapNode);

			if (isNotVisible(grantedOperations, fullMapNode)) {
				continue;
			}
			// 递归处理
			processChildren(roledNode, fullMapNode.getChildren(),
					grantedOperations);
			visibleChilren.add(roledNode);
		}

		parent.setChildren(visibleChilren);
	}

	/**
	 * 是否 fullMapNode 不可见
	 * 
	 * @param grantedOperations
	 * @param fullMapNode
	 * @return
	 */
	private boolean isNotVisible(Collection<String> grantedOperations,
			SiteNodeVO fullMapNode) {
		return !fullMapNode.isVisible()
				|| !SiteMapSecurityUtil.checkVisible(fullMapNode, fullMapNode
						.getChildren(), grantedOperations);
	}

	/* (non-Javadoc)
	 * @see org.ccay.sitemap.service.internal.ISiteMapBuilder#buildWholeSiteMapByLanguage(java.util.List, java.lang.String)
	 */
	public SiteNodeVO buildWholeSiteMapByLanguage(
			List<SiteNodeVO> siteMapNodes, String language)
			throws SiteMapApplicationException {
		return buildWholeSiteMapByLanguage(siteMapNodes, 0, language);
	}

	/* (non-Javadoc)
	 * @see org.ccay.sitemap.service.internal.ISiteMapBuilder#buildWholeSiteMapByLanguage(java.util.List, int, java.lang.String)
	 */
	public SiteNodeVO buildWholeSiteMapByLanguage(
			List<SiteNodeVO> siteMapNodes, int parentId, String language)
			throws SiteMapApplicationException {
		SiteNodeVO rootNode = getRootNode(siteMapNodes, parentId);

		Map<Integer, SiteNodeVO> allNodesMapping = new HashMap<Integer, SiteNodeVO>(siteMapNodes.size());
		//把所有节点保存进map
		for (SiteNodeVO node : siteMapNodes) {
			allNodesMapping.put(node.getSiteNodeId(), node);
		}

		buildAllToTree(rootNode, siteMapNodes, allNodesMapping, language);
		return rootNode;
	}
}
